﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PetGo
{
    partial class Tree
    {
        //public static Dictionary<int, Dictionary<int, double>> myStartposBiasCache = new Dictionary<int, Dictionary<int, double>>();
        public static double logMoveHist;
        //public static double sqrtMoveHist;
        public static int mylastStartpos = -2;
        public static int mytreecapture = -1;


        private double GetBiasForTreeSelect19(int pos)
        {
            if (myRootBoard.myboardsize < 19) return 0;
            //if (myStartpos == 0)
            //{
            //    if (myStartposBiasCache.ContainsKey(myStartpos))
            //    {
            //        if (myStartposBiasCache[myStartpos].ContainsKey(pos))
            //        {
            //            //docompare = true; 
            //            return myStartposBiasCache[myStartpos][pos] / (vorkommen / (15 - 2 * logMoveHist) + 1);
            //        }
            //    }
            //    else
            //    {
            //        myStartposBiasCache[myStartpos] = new Dictionary<int, double>();
            //    }
            //}
            double factor = (vorkommen / (15 - 2 * logMoveHist) + 1);
            // line bias
            double bias = 0;
            bool isSerious = false;

            //
            //Dictionary<int, int> theNei1 = Group.getNeighbors_rad(pos, playOutBoard, 1);
            //int owngroup = -1;
            //int opgroup = -1;
            //foreach (int c in theNei1.Values)
            //{
            //    if (playOutBoard.myGroup[c].myColor == playOutBoard.mytoMove && playOutBoard.myGroup[c].alive < playOutBoard.myGroup[c].dead * 3 && playOutBoard.myGroup[c].alive * 3 > playOutBoard.myGroup[c].dead) owngroup = c;
            //    if (playOutBoard.myGroup[c].myColor != playOutBoard.mytoMove && playOutBoard.myGroup[c].alive > playOutBoard.myGroup[c].dead) opgroup = c;
            //}

            //// there is a group struggling
            //if (owngroup>-1 && opgroup>-1)
            //{
            //    foreach (int c in theNei1.Values)
            //    {
            //        int libown = playOutBoard.myGroup[owngroup].getLibertyCountNoCache(playOutBoard);
            //        int libop = playOutBoard.myGroup[opgroup].getLibertyCountNoCache(playOutBoard);
            //        if (libown + Group.getLibertyCount(pos, playOutBoard) > libop)
            //        {
            //            if (libown < libop)
            //            {
            //                bias += 0.1 / Math.Sqrt(vorkommen + 1);
            //            }
            //            if (libown == libop)
            //            {
            //                bias +=  0.2/ Math.Sqrt(vorkommen + 1);
            //            }

            //        }
            //    }
            //}

            double bias_localresponse = 0;
            int lastpos = -1;

            //local answers prefered (not attach)
            if (myMoveHistory.Count > 0 || playOutBoard.mymovehistory.Count > 0)
            {
                if (playOutBoard.mymovehistory.Count > 0)
                {
                    lastpos = playOutBoard.mymovehistory[playOutBoard.mymovehistory.Count - 1];
                }
                else
                {
                    lastpos = myMoveHistory[myMoveHistory.Count - 1];
                }
                if (playOutBoard.mymovehistory.Count == 0)
                {
                    //if (mylastMoveCache3 == null)
                    //{
                    //    mylastMoveCache3 = Group.getNeighbors_Fields_rad(
                    //    lastpos,
                    //    playOutBoard,
                    //    3);
                    //}
                    if (mylastMoveCache2 == null)
                    {
                        mylastMoveCache2 = Group.getNeighbors_rad(
                        lastpos,
                        playOutBoard,
                        1);
                    }
                    if (playOutBoard.getdistance_int(pos, lastpos) < 15)
                    {
                        bias_localresponse = 1 / factor;
                    }
                    //if (mylastMoveCache3.ContainsKey(pos))
                    //{
                    //    bias_localresponse = 1 / factor;
                    //}
                }
            }

            // getcapture moves
            if (mylastStartpos != myStartpos)
            {
                mytreecapture = -1;
                //if (lastpos > -1)
                //{
                //    Board.lastMove = lastpos;
                //    Board.lastGroup = playOutBoard.myGroup[playOutBoard.myGroupPosition[lastpos]];
                //    mytreecapture = playOutBoard.getPlayOutMoveFromLast();
                //}
                if (lastpos > -1 && playOutBoard.myGroup[playOutBoard.myGroupPosition[lastpos]].myLibs.Count == 1)
                {
                    mytreecapture = playOutBoard.myGroup[playOutBoard.myGroupPosition[lastpos]].myLibs.ElementAt(0).Key;
                }
                mylastStartpos = myStartpos;
            }
            if (pos == mytreecapture)
            {
                bias += 10 / factor/ (myStartpos+2);
            }

            // 3 and 4 line prefered
            int x = myRootBoard.myboardsize / 2 - Math.Abs(pos % myRootBoard.myboardsize - (myRootBoard.myboardsize / 2));
            int y = myRootBoard.myboardsize / 2 - Math.Abs(pos / myRootBoard.myboardsize - (myRootBoard.myboardsize / 2));
            if (playOutBoard.mymovehistory.Count == 0)
            {
                Dictionary<int, int> theradNei1Group = Group.getNeighbors_rad(pos, playOutBoard, 1);
                Dictionary<int, int> theradNei3Group = null;
                //Dictionary<int, int> theradNei4Group = null;
                Dictionary<int, int> theradNei2Group = Group.getNeighbors_rad(pos, playOutBoard, 2);
                int theradNei1 = theradNei1Group.Count;
                int theradNei2 = theradNei2Group.Count;
                int theradNei3 = 99;
                //int theradNei4 = 99;
                int theradNei6 = 99;

                if (myMoveHistory.Count < playOutBoard.myboardsize * playOutBoard.myboardsize / 5)
                {
                    theradNei3Group = Group.getNeighbors_rad(pos, playOutBoard, 3);
                    theradNei3 = theradNei3Group.Count;
                }
                if (myMoveHistory.Count < 20)
                {
                    //theradNei4Group = Group.getNeighbors_rad(pos, playOutBoard, 4);
                    //theradNei4 = theradNei4Group.Count;
                    theradNei6 = Group.getNeighbors_rad(pos, playOutBoard, 6).Count;
                }
                double biasf = 0.1;
                //double biasf = bias_localresponse;
                // free space ist good
                if (theradNei1 == 0) biasf += 0.2;
                if (theradNei2 == 0) biasf += .5;
                if (theradNei3 == 0) biasf += 1;
                //if (theradNei4 == 0) biasf += 0.5;
                if (theradNei6 == 0) biasf += 1;
                if (lastpos > -1)
                {
                    //opponent attached
                    Group thelastGroup = playOutBoard.myGroup[playOutBoard.myGroupPosition[lastpos]];
                    if (mylastMoveCache2.Count > 0)
                    //&& mylastMoveCache3.ContainsKey(pos))
                    {
                        Group own = playOutBoard.myGroup[mylastMoveCache2.FirstOrDefault().Value];
                        foreach (int nei in mylastMoveCache2.Values)
                        {
                            if (playOutBoard.myGroup[nei].myColor != thelastGroup.myColor)
                            {
                                own = playOutBoard.myGroup[nei];
                                if (own.myColor != thelastGroup.myColor && x > 1 && y > 1 && own.getLibertyCount(playOutBoard) > 2 && Group.getNeighbors_Fields_rad(lastpos, playOutBoard, 1).ContainsKey(pos))
                                {
                                    if (own.myLibs.ContainsKey(pos))
                                    {
                                        // pushing from behind
                                        bool ownisattached = false;
                                        foreach (int nei1 in thelastGroup.myNeighbors.Keys)
                                        {
                                            if (own.myNeighbors.ContainsKey(nei1))
                                            {
                                                ownisattached = true;
                                            }
                                        }
                                        //if (!mylastMoveCache3.ContainsKey(pos))
                                        //{
                                        //    ;
                                        //}
                                        if (Group.getLibertyCount(pos, playOutBoard) < 3
                                            //&& thelastGroup.myNeighbors.ContainsKey(own.myposition)
                                            && ownisattached
                                            )
                                        {
                                            if (own.myLibs.Count > 7 || own.myEyes.Count > 1)
                                            {
                                                bias -= 2 / factor;
                                            }
                                            else
                                            {
                                                bias -= 5 / factor;
                                            }
                                        }
                                        if (own.myLibs.Count > 7 || own.myEyes.Count > 1)
                                        {
                                            bias += 2 / factor;
                                        }
                                        else
                                        {
                                            bias += 5 / factor;
                                        }
                                        if (thelastGroup.myLibs.ContainsKey(pos))
                                        {
                                            bias += 1 / factor;
                                        }
                                    }
                                }
                            }
                        }
                        
                    }
                    //// higher than 4th line is bad in the fuseki
                    //if (x > 3 && y > 3 && myMoveHistory.Count < myRootBoard.myboardsize * myRootBoard.myboardsize / 5)
                    //{
                    //    bias -= 1 / factor;
                    //    if (myMoveHistory.Count < myRootBoard.myboardsize * myRootBoard.myboardsize / 10)
                    //    {
                    //        bias -= 0.8 / factor;
                    //    }
                    //}
                    // we don't like 2th line in the fuseki
                    if ((x < 2 || y < 2) && myMoveHistory.Count < myRootBoard.myboardsize * myRootBoard.myboardsize / 5)
                    {
                        bias -= 0.9 / factor;
                    }
                    //// 7 take out last move
                    //if (thelastGroup.getLibertyCount(playOutBoard) == 1)
                    //{
                    //    if (thelastGroup.myLibs.ContainsKey(pos))
                    //    {
                    //        bias += 3 / factor;
                    //    }
                    //}
                    // 8 local runaway with 3 libs
                    List<int> doneownGroups = new List<int>();
                    foreach (int thenei in mylastMoveCache2.Keys)
                    {
                        if (playOutBoard.myGroupPosition.ContainsKey(thenei) && playOutBoard.myGroup[playOutBoard.myGroupPosition[thenei]].myColor != myColor)
                        {
                            Group own = playOutBoard.myGroup[playOutBoard.myGroupPosition[thenei]];
                            // for one Group only once bias
                            if (doneownGroups.Contains(own.myposition)) continue;
                            doneownGroups.Add(own.myposition);
                            // atari own group
                            if (own.getLibertyCount(playOutBoard) == 1)
                            {
                                // take out one of the opponents groups
                                foreach (int opp in own.myNeighbors.Keys)
                                {
                                    if (playOutBoard.myGroupPosition.ContainsKey(opp)
                                        //&& playOutBoard.myGroup[playOutBoard.myGroupPosition[opp]].myColor == myColor
                                        && playOutBoard.myGroup[playOutBoard.myGroupPosition[opp]].getLibertyCount(playOutBoard) == 1
                                        && playOutBoard.myGroup[playOutBoard.myGroupPosition[opp]].myLibs.ContainsKey(pos)
                                        && (playOutBoard.myGroup[playOutBoard.myGroupPosition[opp]].myFields.Count > 1 || Group.getLibertyCount(pos, playOutBoard) > 0)
                                        )
                                    {
                                        bias += 5 / factor;
                                        isSerious = true;
                                    }
                                }
                                if (own.myLibs.ContainsKey(pos))
                                {
                                    int libpos = Group.getLibertyCount(pos, playOutBoard);
                                    //if (libpos > 2)
                                    //{
                                    //    bias += 2 / factor;
                                    //    isSerious = true;
                                    //}
                                    //else
                                    //{

                                    int libs = Group.getLibertyCount_full(pos, myRootBoard, 3);
                                    //foreach (int nei in Group.getNeighbors(pos, myRootBoard.myboardsize).Keys)
                                    //{
                                    //    if (!playOutBoard.myGroupPosition.ContainsKey(nei))
                                    //    {
                                    //        ++libs;
                                    //        continue;
                                    //    }
                                    //    if ((playOutBoard.myGroup[playOutBoard.myGroupPosition[nei]].myColor
                                    //            == myColor))
                                    //    {
                                    //        if (
                                    //            playOutBoard.myGroup[playOutBoard.myGroupPosition[nei]]
                                    //                .getLibertyCount(playOutBoard) == 1)
                                    //        {
                                    //            //bias += 2 / factor;
                                    //            libs = 99;
                                    //            break;
                                    //        }
                                    //    }
                                    //    else
                                    //    {
                                    //        libs +=
                                    //            playOutBoard.myGroup[playOutBoard.myGroupPosition[nei]]
                                    //                .getLibertyCount(playOutBoard) - 1;
                                    //    }
                                    //}
                                    if (libs > 2)
                                    {
                                        bias += 1 / factor;
                                        isSerious = true;
                                    }
                                    if (libs > 3)
                                    {
                                        bias += 3 / factor;
                                        if (libpos == 3)
                                        {
                                            bias += 5 / factor;
                                        }
                                        isSerious = true;
                                    }
                                    if (libs == 1)
                                    {
                                        bias -= 3 / factor;
                                        isSerious = true;
                                    }
                                    if (own.myFields.Count > 1 && libs <= 2)
                                    {
                                        bias -= 10 / factor;
                                        isSerious = true;
                                    }
                                    //}
                                }
                            }
                        }
                    }
                    //// connect if cut is possible
                    //if (theradNei1Group.Count >= 4)
                    //{
                    //    List<int> own = new List<int>();
                    //    List<int> opp = new List<int>();
                    //    foreach (int nei in theradNei1Group.Values)
                    //    {
                    //        if (myRootBoard.myGroup[nei].myColor == myRootBoard.mytoMove && !own.Contains(nei))
                    //        {
                    //            own.Add(nei);
                    //        }
                    //        if (myRootBoard.myGroup[nei].myColor != myRootBoard.mytoMove && !opp.Contains(nei) && myRootBoard.myGroup[nei].myLibs.Count > 2)
                    //        {
                    //            opp.Add(nei);
                    //        }
                            
                    //    }
                    //    if (opp.Count == 2 && own.Count == 2)
                    //    {
                    //        bias += 2 / factor;
                    //        isSerious = true;
                    //    }
                    //}
                    // hane on the 2-th line
                    if (((x == 1 && y > 0) || (y == 1 && x > 0)) && theradNei1Group.Count == 2)
                    {
                        Group own = null;
                        Group opp = null;
                        foreach (int nei in theradNei1Group.Values)
                        {
                            if (myRootBoard.myGroup[nei].myColor == myRootBoard.mytoMove)
                            {
                                own = myRootBoard.myGroup[nei];
                            }
                            else
                            {
                                opp = myRootBoard.myGroup[nei];
                            }
                        }
                        if (own != null && opp != null && own.myLibs.Count > 2 && opp.myLibs.Count == 3
                            && opp.myFields.Count == 1 && opp.myLibs.ContainsKey(pos))
                        {
                            int xl = myRootBoard.myboardsize / 2
                                     - Math.Abs(
                                         opp.myposition % myRootBoard.myboardsize - (myRootBoard.myboardsize / 2));
                            int yl = myRootBoard.myboardsize / 2
                                     - Math.Abs(
                                         opp.myposition / myRootBoard.myboardsize - (myRootBoard.myboardsize / 2));
                            int xo = myRootBoard.myboardsize / 2
                                                                 - Math.Abs(
                                                                     own.myposition % myRootBoard.myboardsize - (myRootBoard.myboardsize / 2));
                            int yo = myRootBoard.myboardsize / 2
                                     - Math.Abs(
                                         own.myposition / myRootBoard.myboardsize - (myRootBoard.myboardsize / 2));

                            if (((xl == 2 && yl > 2) || (yl == 2 && xl > 2)) && ((xo > 1) && (yo > 1)))
                            {
                                if (Group.getLibertyCount(pos, playOutBoard) == 3)
                                {
                                    bias += 3 / factor;
                                    isSerious = true;
                                }

                            }
                        }
                    }
                    // connect on the 3-th line
                    if (((x == 2 && y > 0) || (y == 2 && x > 0)) && theradNei1Group.Count >= 4)
                    {
                        List<int> tmpGroups = new List<int>();
                        int owncount = 0;
                        int oppcount = 0;
                        bool correctConnect = false;
                        foreach(int cGroupkey in theradNei1Group.Values)
                        {
                            if (tmpGroups.Contains(cGroupkey)) continue;
                            tmpGroups.Add(cGroupkey);
                            if (myRootBoard.myGroup[cGroupkey].myColor == myRootBoard.mytoMove)
                            {
                                ++owncount; 
                            }
                            else
                            {
                                ++oppcount;
                                if (myRootBoard.myGroup[cGroupkey].myLibs.Count>2)
                                {
                                    foreach(int field in myRootBoard.myGroup[cGroupkey].myFields.Keys)
                                    {
                                        if(myRootBoard.getx(field) == 1 || myRootBoard.gety(field) == 1)
                                        {
                                            correctConnect = true;
                                        }
                                    }
                                }
                            }
                        }
                        if (correctConnect && owncount >= oppcount && owncount > 1)
                        {
                            correctConnect = false;
                            int grouppos = -1;
                            foreach (int nei in Group.getNeighbors(pos, myRootBoard.myboardsize).Keys)
                            {
                                if (myRootBoard.myGroupPosition.ContainsKey(nei) && myRootBoard.myGroup[myRootBoard.myGroupPosition[nei]].myColor == myRootBoard.mytoMove)
                                {
                                    if (grouppos == -1)
                                    {
                                        grouppos = myRootBoard.myGroupPosition[nei];
                                    }
                                    else
                                    {
                                        if (grouppos == myRootBoard.myGroupPosition[nei]) continue;
                                        correctConnect = true;
                                        break;
                                    }
                                }
                            }
                            if (correctConnect)
                            {
                                bias += 3 / factor;
                                isSerious = true;
                            }
                            else
                            {
                                ;
                            }
                        }
                    }
                    // connect on the second line
                    if (((x == 1 && y > 0) || (y == 1 && x > 0)) && theradNei1Group.Count >= 3)
                    {
                        if (Group.getLibertyCount_full(pos, playOutBoard, 4) >= 5)
                        {
                            bool doconnect = true;
                            foreach(int g in theradNei1Group.Values)
                            {
                                if (playOutBoard.myGroup[g].myFields.Count == 1 && (playOutBoard.getx(g) == 1 || playOutBoard.gety(g) == 1) && playOutBoard.myGroup[g].myLibs.Count == 2 && playOutBoard.myGroup[g].myColor == playOutBoard.mytoMove)
                                {
                                    foreach (int nei in playOutBoard.myGroup[g].myNeighbors.Keys)
                                    {
                                        if (playOutBoard.myGroupPosition.ContainsKey(nei) && playOutBoard.myGroup[playOutBoard.myGroupPosition[nei]].myLibs.Count < 3)
                                        {
                                            doconnect = false;
                                            break;
                                        }
                                    }
                                }
                                if (!doconnect) break;
                            }
                            if (doconnect)
                            {
                                bias += 3 / factor;
                            }
                        }
                    }
                }
                if ((x == 2 || x == 3) && (y > 1))
                {
                    bias += biasf / factor;
                }
                if ((y == 2 || y == 3) && (x > 1))
                {
                    bias += biasf / factor;
                }
                if ((y == 2 || y == 3) && (x == 2 || x == 3))
                {
                    bias += biasf / factor;
                }

                // 3 avoid selfatari
                int ownlibs = 0;

                foreach (int nei in Group.getNeighbors(pos, playOutBoard.myboardsize).Keys)
                {
                    if (playOutBoard.myGroupPosition.ContainsKey(nei))
                    {

                        if (playOutBoard.myGroup[playOutBoard.myGroupPosition[nei]].myColor != myColor)
                        {
                            ownlibs +=
                                playOutBoard.myGroup[playOutBoard.myGroupPosition[nei]].getLibertyCount(
                                    playOutBoard) - 1;
                        }
                        else
                        {
                            if (playOutBoard.myGroup[playOutBoard.myGroupPosition[nei]].getLibertyCount(
                                playOutBoard) == 1)
                            {
                                ownlibs += 1;
                            }
                        }
                    }
                    else
                    {
                        ownlibs += 1;
                    }
                }
                if (ownlibs < 3)
                {
                    bias -= 1 / factor;
                }
                if (ownlibs < 2)
                {
                    bias -= 8 / factor;
                }

                // dont't play 2-2 in the corner with one stone in the corner allready
                if (theradNei2 == 1 && x == 1 && y == 1)
                {
                    bias -= 8 / factor;
                }

                // 3 line kema to 4th line stone
                if (theradNei2 == 1 && theradNei3 < 3)
                {
                    Group theG = playOutBoard.myGroup[theradNei2Group.FirstOrDefault().Value];
                    if (theG.myFields.Count == 1
                        && myColor == theG.myColor
                        )
                    {
                        if (theradNei3 == 1)
                        {
                            if ((playOutBoard.getx(theG.myposition) == 3 && playOutBoard.getx(pos) == 2 && playOutBoard.gety(pos) > 1)
                                || (playOutBoard.gety(theG.myposition) == 3 && playOutBoard.gety(pos) == 2 && playOutBoard.getx(pos) > 1))
                            {
                                if (playOutBoard.getdistance_int(theG.myposition, pos) == 5)
                                    //&& playOutBoard.getdistance(theG.myposition, pos) < 2.24)
                                {
                                    if (theradNei3 == 1)
                                    {
                                        bias += 2.6 / factor;
                                    }

                                }
                            }
                        }
                    }
                    if (theG.myFields.Count == 1
                   && myColor != theG.myColor
                   )
                    {
                        if (theradNei3 == 2 && theradNei1 == 0)
                        {
                            if (playOutBoard.getx(pos) > 1 && playOutBoard.gety(pos) > 1)
                            {
                                if ( 
                                    (playOutBoard.getx(theG.myposition) == 2 || playOutBoard.getx(theG.myposition) == 3)
                                    && (playOutBoard.gety(theG.myposition) == 2 || playOutBoard.gety(theG.myposition) == 3)
                                     )
                                {
                                    if (playOutBoard.getx(pos) < 4 || playOutBoard.gety(pos) < 4)
                                    {
                                        if (playOutBoard.myGroup[theradNei3Group.ElementAt(1).Value].myColor == playOutBoard.myGroup[theradNei3Group.FirstOrDefault().Value].myColor && playOutBoard.getdistance_int(theradNei3Group.ElementAt(1).Key, theradNei3Group.FirstOrDefault().Key) < 10)
                                        {
                                            ;
                                        }
                                        else
                                        {
                                            bias += 3.6 / factor;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                

                // 4 not attach opponent
                if (theradNei1 == 1 && theradNei2 == 1)
                {
                    // don't block 3-3 invasion
                    if (x == 2 && y == 2 && playOutBoard.myGroup[theradNei1Group.FirstOrDefault().Value].myFields.Count == 1)
                    {
                        // 3-3 invasion under lonley 4-4 stone is good
                        if (
                               (playOutBoard.myGroup[theradNei1Group.FirstOrDefault().Value].myFields.FirstOrDefault().Key == 3+3*playOutBoard.myboardsize)
                            || (playOutBoard.myGroup[theradNei1Group.FirstOrDefault().Value].myFields.FirstOrDefault().Key == -4+4*playOutBoard.myboardsize)
                            || (playOutBoard.myGroup[theradNei1Group.FirstOrDefault().Value].myFields.FirstOrDefault().Key == playOutBoard.myboardsize * playOutBoard.myboardsize - 4 - 3 * playOutBoard.myboardsize)
                            || (playOutBoard.myGroup[theradNei1Group.FirstOrDefault().Value].myFields.FirstOrDefault().Key == playOutBoard.myboardsize * playOutBoard.myboardsize - 1 + 4 - 4*playOutBoard.myboardsize)
                           )
                        {
                            bias += 0.2 / factor;
                            if (theradNei3 == 1)
                            {
                                bias += 0.7 / factor;
                            }
                        }
                    }
                    else
                    {
                        bias -= 5 / factor;
                    }
                }
                if (theradNei1 == 2
                    && playOutBoard.myGroup[theradNei1Group.FirstOrDefault().Value].myColor ==
                     playOutBoard.myGroup[theradNei1Group.ElementAt(1).Value].myColor)
                {
                    bias -= 5 / factor;
                }
                if (theradNei2 == 2
                    && playOutBoard.myGroup[theradNei2Group.FirstOrDefault().Value].myColor ==
                     playOutBoard.myGroup[theradNei2Group.ElementAt(1).Value].myColor
                    && Group.getLibertyCount_full(pos, myRootBoard, 3) <= 3)
                {
                    bias -= 3 / factor;
                }
                 //extension is good
                if ((x == 2 || x == 3) && (y > 1) || (y == 2 || y == 3) && (x > 1))
                {
                    if (theradNei3 == 1 && theradNei1 == 0)
                    {
                        if (playOutBoard.myGroup[theradNei3Group.FirstOrDefault().Value].myColor != myColor)
                        {
                            bias += 0.4 / factor;
                        }
                        
                    }
                    if (theradNei3 == 1 && theradNei2 == 0)
                    {
                        if (playOutBoard.myGroup[theradNei3Group.FirstOrDefault().Value].myColor != myColor)
                        {
                            bias += 0.4 / factor;
                        }
                        
                    }
                    if (theradNei3 == 2 && theradNei1 == 0)
                    {
                        if (playOutBoard.myGroup[theradNei3Group.FirstOrDefault().Value].myColor != playOutBoard.myGroup[theradNei3Group.ElementAt(1).Value].myColor)
                        {
                            bias += 0.4 / factor;
                        }
                    }
                    if (theradNei3 == 2 && theradNei2 == 0)
                    {
                        if (playOutBoard.myGroup[theradNei3Group.FirstOrDefault().Value].myColor != playOutBoard.myGroup[theradNei3Group.ElementAt(1).Value].myColor)
                        {
                            bias += 0.4 / factor;
                        }
                    }
                    if (theradNei3 == 2 && theradNei1 == 0 && (playOutBoard.getx(pos) == 3 || playOutBoard.gety(pos) == 3))
                    {
                        if (playOutBoard.myGroup[theradNei3Group.FirstOrDefault().Value].myColor == playOutBoard.myGroup[theradNei3Group.ElementAt(1).Value].myColor 
                            && playOutBoard.myGroup[theradNei3Group.FirstOrDefault().Value].myColor != myColor)
                        {
                            int pos1 = playOutBoard.myGroup[theradNei3Group.FirstOrDefault().Value].myposition;
                            int pos2 = playOutBoard.myGroup[theradNei3Group.ElementAt(1).Value].myposition;
                            if (playOutBoard.gety(pos) == 3 && playOutBoard.getx(pos) > 2 ||
                                playOutBoard.getx(pos) == 3 && playOutBoard.gety(pos) > 2)
                            {
                                if (playOutBoard.getdistance_int(pos1, pos2) > 12)
                                {
                                    bias += 0.8 / factor;
                                }
                                if (playOutBoard.getdistance_int(pos1, pos2) > 20)
                                {
                                    bias += 3 / factor;
                                }
                            }
                        }
                    }
                }
                // corner enclosure
                if (x < 6 &&  y < 6 && x > 1 && y > 1 && (x < 4 || y < 4))
                {
                    if (theradNei2 == 1 && theradNei1 == 0 && theradNei3 == 1)
                    {
                        Group cGroup = playOutBoard.myGroup[theradNei2Group.FirstOrDefault().Value];
                        int pos1x = playOutBoard.getx(cGroup.myposition);
                        int pos1y = playOutBoard.gety(cGroup.myposition);
                        if (cGroup.myColor != myColor && cGroup.myFields.Count == 1 &&
                            (pos1x != 2 || pos1y != 2))
                        {
                            if (playOutBoard.getdistance_int(pos, cGroup.myposition) >= 4)
                            {
                                if ((x > y && pos1x <= pos1y && pos1y != y) || (y > x && pos1y <= pos1x && pos1x != x))
                                {
                                    bias += 3.2 / factor;
                                }
                            }                            
                        }
                    }
                }

                // connect secondline with two libs
                if (theradNei1 >= 3 && (x == 1 || y == 1))
                {
                    if (Group.getLibertyCount(pos, playOutBoard) == 2 && Group.getLibertyCount_full(pos, playOutBoard, 3) > 3)
                    {
                        List<int> anzgroup = new List<int>();
                        foreach (int group in theradNei1Group.Values)
                        {
                            if (!anzgroup.Contains(group))
                            {
                                anzgroup.Add(group);

                            }
                        }
                        if (anzgroup.Count >= 3)
                        {
                            bias += 1.6 / factor;
                        }
                    }
                }
                // higher than 4th line is bad in the fuseki
                if (x > 3 && y > 3 && myMoveHistory.Count < myRootBoard.myboardsize * myRootBoard.myboardsize / 5)
                {
                    bias -= 1 / factor;
                    if (myMoveHistory.Count < myRootBoard.myboardsize * myRootBoard.myboardsize / 10)
                    {
                        bias -= 0.8 / factor / (myStartpos + 1) / (myStartpos + 1) / (myStartpos + 1);
                    }
                }
               
            }

            int con = 0;
            int minopp = 9;
            foreach (int nei in Group.getNeighbors(pos, playOutBoard.myboardsize).Keys)
            {
                if (playOutBoard.myGroupPosition.ContainsKey(nei))
                {
                    if (playOutBoard.myGroup[playOutBoard.myGroupPosition[nei]].myColor == playOutBoard.mytoMove)
                    {
                        if (playOutBoard.myGroup[playOutBoard.myGroupPosition[nei]].myLibs.Count == 2)
                        {
                            ++con;
                        }
                    }
                    else
                    {
                        if (Group.getLibertyCount_full(nei, playOutBoard, 6) < minopp)
                        {
                            minopp = Group.getLibertyCount_full(nei, playOutBoard, 8) - 1;
                        }
                    }
                }
            }
            if (con == 2)
            {
                if (Group.getLibertyCount_full(pos, playOutBoard, 3) > 3)
                {
                    bias += 5 / factor / (myStartpos / 2 + 1);
                }
            }
            if (minopp < 9)
            {
                if (Group.getLibertyCount_full(pos, playOutBoard, minopp) > minopp)
                {
                    bias += 2 / factor / (myStartpos / 2 + 1);
                }
            }
            // first line not in fuseki
            if ((x == 0 || y == 0) && myMoveHistory.Count + playOutBoard.mymovehistory.Count < (myRootBoard.myboardsize * myRootBoard.myboardsize / 5))
            {
                bias -= 2 / factor / (myStartpos + 1) / (myStartpos + 1) / (myStartpos + 1);
            }

            

            // line bias
            //bias += -Math.Abs(2.5 - x) * Math.Abs(2.5 - y) / 10000000 / factor * (10+Board.myRandom.NextDouble());
            if (myStartpos == 0)
            {
                // empty triangle
                if (playOutBoard.isEmptyTriangle(pos) && !isSerious)
                {
                    if (bias > 0) bias = 0;
                    //bias -= 1 / factor;
                }
            }



            //if (Tree.myRootBoard.mytoMove == color.white)
            {
                if (patternmoves1.ContainsKey(pos))
                {
                    long sum = 0;
                    foreach(int s in patternmoves1.Values)
                    {
                        sum +=s;
                    }
                    //if (patternmoves1[pos] < 5)
                    //{
                    //    bias += 6 / factor / (myStartpos/2 + 1) * Math.Sqrt((double)patternmoves1[pos] / sum);
                    //}
                    //else
                    //{
                        bias += 10 / factor / (myStartpos/2 + 1) * Math.Sqrt((double)patternmoves1[pos] / sum);
                        double test = Math.Log10(sum);
                        ;
                    //}
                    
                    //++Board.randmovescount;
                }
            }

            //if (myRootBoard.mytoMove == color.black)
            foreach(int g in myweakGroups.Keys)
            {
                foreach(int f in myRootBoard.myGroup[g].myFields.Keys)
                {
                    if (myRootBoard.getdistance_int(pos, f) < 10)
                    {
                        bias += 0.5 / factor / (myStartpos / 2 + 1);
                        break;
                    }
                }
            }
               

            bias += bias_localresponse;

            //if (myStartpos == 0)
            //{
                
            //    myStartposBiasCache[myStartpos][pos] = bias * factor * Tree.myRootBoard.myGame.mysecondstothink / 19;
            //}
            return bias;
        }

        public void writebias()
        {
            getPatternMoves();
            for (int x = 0; x < myRootBoard.myboardsize; ++x)
            {
                Console.Write("| "+x.ToString("00")+ " ");
            }
            Console.Write("|");
            for (int y = 0; y < myRootBoard.myboardsize; ++y)
            {
                Console.WriteLine("");
                Console.Write("|");
                for (int x = 0; x < myRootBoard.myboardsize; ++x)
                {
                    int pos = x + y * myRootBoard.myboardsize;
                    if (!myRootBoard.myGroupPosition.ContainsKey(pos))
                    {
                        if (GetBiasForTreeSelect19(pos) < 0)
                        {
                            Console.Write(GetBiasForTreeSelect19(pos).ToString("0.0"));
                        }
                        else
                        {
                            Console.Write("+" + GetBiasForTreeSelect19(pos).ToString("0.0"));

                        }
                    }
                    else
                    {
                        if (myRootBoard.myGroup[myRootBoard.myGroupPosition[pos]].myColor == color.black)
                        {
                            Console.Write(" BB ");
                        }
                        else
                        {
                            Console.Write(" WW ");
                        }
                    }
                    Console.Write(" ");
                }
                Console.Write("|");
                Console.WriteLine("");
            }
            Board.capturemoves1.Clear();
        }
    }
}
